#ifndef MAIN_H
#define MAIN_H

//The headers
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include <string>
#include <fstream>
#include <iostream>
#include <queue>
#include <functional>

//Screen attributes
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;

//The frame rate
const int FRAMES_PER_SECOND = 10;

///=================================================
/// CHARACTER-RELATED CONSTANTS
///=================================================

//The player dimensions
const int PLAYER_X_POS = 704;
const int PLAYER_Y_POS = 864;
const int PLAYER_WIDTH = 32;
const int PLAYER_HEIGHT = 32;

const int ENEMY_X_POS = 32;
const int ENEMY_Y_POS = 32;

//The directions of the player sprite
const int PLAYER_DOWN = 0;
const int PLAYER_LEFT = 1;
const int PLAYER_RIGHT = 2;
const int PLAYER_UP = 3;

//Number of "animations" for player sprite
const int PLAYER_ANIMATIONS = 3;

//The player's constant velocity
const int PLAYER_VELOCITY = PLAYER_HEIGHT / 2;

//The dimensions of the character sprite sheet
const int CHARSHEET_WIDTH = 96;
const int CHARSHEET_HEIGHT = 128;

///=================================================
/// LEVEL-RELATED CONSTANTS
///=================================================

//The dimensions of the level
const int LEVEL_WIDTH = 1280;
const int LEVEL_HEIGHT = 960;

//Tile constants
const int TILE_WIDTH = 32; //80x80, 192, 12
const int TILE_HEIGHT = 32;
const int TOTAL_TILES= 1200;
const int TILE_SPRITES = 25;

//The dimensions of the background tile sheet
const int TILESHEET_WIDTH = 160;
const int TILESHEET_HEIGHT = 160;

//Enummeration of tile types
enum tile_t { GRASS, SUNFLOWER, ROSE, VIOLET, DAISY, 
              LOGLEFT, LAKEUPPERLEFT, LAKELEFT, LAKELOWERLEFT, SIGN, 
              LOGRIGHT, LAKETOP, LAKECENTER, LAKEDOWN, MUSHROOM,
              WEED, LAKEUPPERRIGHT, LAKERIGHT, LAKELOWERRIGHT, ROCK,
              TREE1UP, TREE1DOWN, TREE2UP, TREE2DOWN, STUMP, PORTALSTR, PORTALEND };
              
// gear indicator constants
const int GEAR_X_POS = 0;
const int GEAR_Y_POS = 0;
const int GEAR_WIDTH = 64;
const int GEAR_HEIGHT = 64;

//ready screen constants
const int READY_X_POS = 32 * 32;
const int READY_Y_POS = 0;
const int READY_WIDTH = 32;
const int READY_HEIGHT = 32;

//Create needed arrays
/*char walkability [mapWidth][mapHeight];
int openList[mapWidth*mapHeight+2];     //1 dimensional array holding ID# of open list items
int whichList[mapWidth+1][mapHeight+1]; //2 dimensional array used to record 
                                        //  whether a cell is on the open list or on the closed list.
int openX[mapWidth*mapHeight+2];        //1d array stores the x location of an item on the open list
int openY[mapWidth*mapHeight+2];        //1d array stores the y location of an item on the open list
int parentX[mapWidth+1][mapHeight+1];   //2d array to store parent of each cell (x)
int parentY[mapWidth+1][mapHeight+1];   //2d array to store parent of each cell (y)
int Fcost[mapWidth*mapHeight+2];	    //1d array to store F cost of a cell on the open list
int Gcost[mapWidth+1][mapHeight+1];     //2d array to store G cost for each cell.
int Hcost[mapWidth*mapHeight+2];	    //1d array to store H cost of a cell on the open list
int pathLength[numberPeople+1];         //stores length of the found path for critter
int pathLocation[numberPeople+1];       //stores current position along the chosen path for critter		
int* pathBank [numberPeople+1];*/

using namespace std;

//The tile
class Tile
{
    private:
    //The attributes of the tile
    SDL_Rect box;

    //The tile type
    int type;

    Tile *parent;
    
    public:
    //Initializes the variables
    Tile( int x, int y, int tileType );

    //Shows the tile
    void show();

    //Get the tile type
    int get_type();

    //Get the collision box
    SDL_Rect get_box();
    
    int f_val, h_val, g_val;
    
    Tile* get_parent();
    bool set_parent( Tile *p );
    
};

//The player
class Player
{
    private:
    //The player's collision box
    SDL_Rect box;

    //The velocity of the player
    int xVel, yVel;
    
    //The current frame of the player
    int frame;
    
    //The animation status
    int status;

    public:
    //Initializes the variables
    Player();

    //Takes key presses and adjusts the player's velocity
    void handle_input();

    //Moves the player
    void move( Tile *tiles[] );

    //Shows the player on the screen
    void show();

    //Sets the camera over the player
    void set_camera();
    
    SDL_Rect getBox();
};

//The enemy
class Enemy
{
    private:
    //The player's collision box
    SDL_Rect box;

    //The velocity of the player
    int xVel, yVel;
    
    //The current frame of the player
    int frame;
    
    //The animation status
    int status;
    
    //Flags whether the enemy bumped into an obstacle
    bool bumped;
    
    //Indicates the last action done by the enemy
    int lastAction;

    public:
    //Initializes the variables
    Enemy();

    //Attempts to find a path towards the player
    int find_path( Tile *tiles[], SDL_Rect playerBox );
    
    //Moves the player
    void move( Tile *tiles[] );

    //Shows the player on the screen
    void show();
    
    SDL_Rect getBox();
};

//The timer
class Timer
{
    private:
    //The clock time when the timer started
    int startTicks;

    //The ticks stored when the timer was paused
    int pausedTicks;

    //The timer status
    bool paused;
    bool started;

    public:
    //Initializes variables
    Timer();

    //The various clock actions
    void start();
    void stop();
    void pause();
    void unpause();

    //Gets the timer's time
    int get_ticks();

    //Checks the status of the timer
    bool is_started();
    bool is_paused();
};

class Gear
{
      private:
      
      SDL_Rect box;
      
      int currentAlpha;
      
      bool gType;
      
      public:
      
      Gear();
      Gear(bool type);
      
      void updateAlpha( float currTime, float timeLimit, bool col );
      void show();
      
      int getCurrentAlpha();
};

class Ready
{
      private:
              
      SDL_Rect box;
      
      bool isVisible;
      
      public:
      
      Ready();
      
      void show();
      
      void setVisible(bool visible);
      
      SDL_Rect getBox();
};

SDL_Surface *load_image( std::string filename );

void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip, bool adjustAlpha );

bool check_collision( SDL_Rect A, SDL_Rect B );

bool init();

bool load_files();

void clean_up( Tile *tiles[] );

void clip_tiles();

void set_char_sprite_clips();

bool set_tiles( Tile *tiles[] );

bool touches_wall( SDL_Rect box, Tile *tiles[] );

int index_of_tile( int row, int col );

int index_of_tileXY( int x, int y );

bool is_in_closed_list( Tile &t, vector<Tile*> tpq );

bool is_in_open_list( Tile &t, priority_queue<Tile> tpq );


#endif
